package com.docmgmt.mvp.controller;

import com.docmgmt.mvp.dto.*;
import com.docmgmt.mvp.service.FolderService;
import com.docmgmt.mvp.service.PermissionService;
import com.docmgmt.mvp.exception.ForbiddenException;
import com.docmgmt.mvp.exception.UnauthorizedException;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * 文件夹管理控制器（v3.0 RBAC权限检查）
 */
@Slf4j
@RestController
@RequestMapping("/api/v1/folders")
@RequiredArgsConstructor
public class FolderController {

    private final FolderService folderService;
    private final PermissionService permissionService;

    /**
     * 创建文件夹
     *
     * POST /api/v1/folders
     */
    @PostMapping
    public Result<FolderVO> createFolder(@Valid @RequestBody CreateFolderRequest request) {
        Long userId = getCurrentUserId();

        // 权限检查：folder:create
        if (!permissionService.checkPermission(userId, "folder", "create")) {
            throw new ForbiddenException("无权限创建文件夹");
        }

        log.info("POST /api/v1/folders - userId={}, folderName={}", userId, request.getName());

        FolderVO folder = folderService.createFolder(request, userId);
        return Result.success("文件夹创建成功", folder);
    }

    /**
     * 获取文件夹列表
     *
     * GET /api/v1/folders?parent_id=xxx&page=1&page_size=20&sort_by=created_at&sort_order=desc
     */
    @GetMapping
    public Result<PagedResult<FolderVO>> listFolders(
            @RequestParam(value = "parent_id", required = false) Long parentId,
            @RequestParam(value = "page", required = false) Integer page,
            @RequestParam(value = "page_size", required = false) Integer pageSize,
            @RequestParam(value = "sort_by", required = false) String sortBy,
            @RequestParam(value = "sort_order", required = false) String sortOrder) {

        Long userId = getCurrentUserId();

        // 权限检查：folder:read
        if (!permissionService.checkPermission(userId, "folder", "read")) {
            throw new ForbiddenException("无权限查看文件夹");
        }

        log.info("GET /api/v1/folders - userId={}, parentId={}", userId, parentId);

        PagedResult<FolderVO> result = folderService.listFolders(
                parentId, userId, page, pageSize, sortBy, sortOrder);
        return Result.success(result);
    }

    /**
     * 获取文件夹树
     *
     * GET /api/v1/folders/tree
     */
    @GetMapping("/tree")
    public Result<List<FolderVO>> getFolderTree() {
        Long userId = getCurrentUserId();

        // 权限检查：folder:read
        if (!permissionService.checkPermission(userId, "folder", "read")) {
            throw new ForbiddenException("无权限查看文件夹");
        }

        log.info("GET /api/v1/folders/tree - userId={}", userId);

        List<FolderVO> tree = folderService.getFolderTree(userId);
        return Result.success(tree);
    }

    /**
     * 获取文件夹详情
     *
     * GET /api/v1/folders/{id}
     */
    @GetMapping("/{id}")
    public Result<FolderVO> getFolderDetail(@PathVariable Long id) {
        Long userId = getCurrentUserId();

        // 权限检查：folder:read（包含资源所有者检查）
        if (!permissionService.checkPermission(userId, "folder:" + id, "read")) {
            throw new ForbiddenException("无权限查看该文件夹");
        }

        log.info("GET /api/v1/folders/{} - userId={}", id, userId);

        FolderVO folder = folderService.getFolderDetail(id);
        return Result.success(folder);
    }

    /**
     * 更新文件夹
     *
     * PUT /api/v1/folders/{id}
     */
    @PutMapping("/{id}")
    public Result<FolderVO> updateFolder(
            @PathVariable Long id,
            @Valid @RequestBody UpdateFolderRequest request) {

        Long userId = getCurrentUserId();

        // 权限检查：folder:update
        if (!permissionService.checkPermission(userId, "folder:" + id, "update")) {
            throw new ForbiddenException("无权限修改该文件夹");
        }

        log.info("PUT /api/v1/folders/{} - userId={}, newName={}", id, userId, request.getName());

        FolderVO folder = folderService.updateFolder(id, request, userId);
        return Result.success("文件夹更新成功", folder);
    }

    /**
     * 删除文件夹
     *
     * DELETE /api/v1/folders/{id}
     */
    @DeleteMapping("/{id}")
    public Result<Void> deleteFolder(@PathVariable Long id) {
        Long userId = getCurrentUserId();

        // 权限检查：folder:delete
        if (!permissionService.checkPermission(userId, "folder:" + id, "delete")) {
            throw new ForbiddenException("无权限删除该文件夹");
        }

        log.info("DELETE /api/v1/folders/{} - userId={}", id, userId);

        folderService.deleteFolder(id, userId);
        return Result.success("文件夹删除成功");
    }

    /**
     * 移动文件夹
     *
     * POST /api/v1/folders/{id}/move
     */
    @PostMapping("/{id}/move")
    public Result<FolderVO> moveFolder(
            @PathVariable Long id,
            @Valid @RequestBody MoveFolderRequest request) {

        Long userId = getCurrentUserId();

        // 权限检查：folder:update（移动文件夹需要update权限）
        if (!permissionService.checkPermission(userId, "folder:" + id, "update")) {
            throw new ForbiddenException("无权限移动该文件夹");
        }

        log.info("POST /api/v1/folders/{}/move - userId={}, targetParentId={}",
                id, userId, request.getTargetParentId());

        FolderVO folder = folderService.moveFolder(id, request, userId);
        return Result.success("文件夹移动成功", folder);
    }

    /**
     * 从Spring Security上下文获取当前用户ID
     */
    private Long getCurrentUserId() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication == null || !authentication.isAuthenticated()) {
            throw new UnauthorizedException("未登录或认证已过期");
        }

        Object principal = authentication.getPrincipal();
        if (principal instanceof Long) {
            return (Long) principal;
        }

        throw new UnauthorizedException("无效的认证信息");
    }
}
